package dianmobile.eistarandroid.network.request;

import android.content.Context;
import android.util.Log;
import android.widget.ImageView;

import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.caches.LruImageCache;
import com.android.volley.caches.LruImageDataCache;
import com.android.volley.cookies.OnCookiesDataChangedListener;
import com.android.volley.images.ImageDataLoader;
import com.android.volley.images.ImageDataOperator;
import com.android.volley.toolbox.ImageLoader;
import com.android.volley.toolbox.Volley;

import java.security.InvalidParameterException;
import java.util.Map;

import dianmobile.eistarandroid.utils.ConstantsData;

/**
 * @author ChameleonChen
 * @date 2015/7/3
 */
public class RequestFactory {

    /**
     * this is a network request queue.
     * it was build in Singleton to save resources of the application.
     */
    private static RequestQueue mRequestQueue = null;

    /**
     * get the network request queue of this application.
     * @param context the application context should be given to let network
     *                request queue use resources of this application.
     */
    public static RequestQueue getRequestQueue(Context context) {
        if (mRequestQueue == null)
            mRequestQueue = Volley.newRequestQueue(context);

        return mRequestQueue;
    }

    /**
     * create a instance {@link com.android.volley.Response.ErrorListener}.
     * @param callback
     * @return
     */
    private static Response.ErrorListener getErrorListener(final RequestCallback callback) {
        return new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                callback.onResult(null, error.toString());
            }
        };
    }

    /**
     * create a instance of a subclass of {@link ByhhAndroidRequest}.
     * @param type  indicate which type of {@link ByhhAndroidRequest}'s subclass should be created.
     * @param params    the request params.
     * @param callback  callback after network request finished.
     * @return
     */
    public static ByhhAndroidRequest buildRequest(RequestType type, Map<String, String> params,
                                           RequestCallback callback) {
        ByhhAndroidRequest result = null;

        String url;
        switch (type) {
            case LOGIN:
                url = "http://dian.hust.edu.cn:81/bbslogin";
                result = new LoginRequest(Request.Method.POST, url, params, callback, getErrorListener(callback));
                break;
            
            case SUBSCRIPTION:
                url = "http://dian.hust.edu.cn:81/bbsbrd?xml=1";
                result = new SubscriptionListRequest(Request.Method.GET, url, null, callback, getErrorListener(callback));
                break;

            case SUB_BOARD:
                String group = params.get("group");
                url = "http://dian.hust.edu.cn:81/bbsboa?" + group +"=&xml=1";
                result = new SubBoardRequest(Request.Method.GET, url, null, callback, getErrorListener(callback));
                break;

            case MYPOSTS:
                String start = params.get(ConstantsData.EXTRA_START_NUM);
                url = "http://dian.hust.edu.cn:81/bbsmyposts?start="+start+"&xml=1";
                result = new MyArticleRequest(Request.Method.GET, url, params, callback, getErrorListener(callback));
                break;

            case ARTICLE_ONE:
                String articleBoardName = params.get(ConstantsData.EXTRA_BOARD_NAME);
                String fileName = params.get(ConstantsData.EXTRA_FILE_NAME);
                url = "http://dian.hust.edu.cn:81/bbsnewtcon?board="+articleBoardName+"&file=" + fileName + "&xml=1";
                result = new GetOneArticleRequest(Request.Method.GET, url, null, callback, getErrorListener(callback));
                break;

            case BOARD_CONTENT:
                String boardName = params.get(ConstantsData.EXTRA_BOARD_NAME);
                String startNum = params.get(ConstantsData.EXTRA_START_NUM);
                url = "http://dian.hust.edu.cn:81/bbsnewtdoc?board="+boardName+"&start="+ startNum+"&xml=1&summary=1";
                result = new BoardContentRequest(Request.Method.GET, url, null, callback, getErrorListener(callback));
                break;

            case USER_DETAIL:
                String userName = params.get(ConstantsData.EXTRA_USER_NAME);
                url = "http://dian.hust.edu.cn:81/bbsqry?userid=" + userName +"&xml=1";
                result = new UserDetailRequest(Request.Method.GET, url, null, callback, getErrorListener(callback));
                break;

            case POST_NEW_ARTICLE:
                url = "http://dian.hust.edu.cn:81/bbssnd?";
                result = new PostRequest(Request.Method.POST, url, params, callback, getErrorListener(callback));
                break;
            case POST_MAIL:
                url = "http://dian.hust.edu.cn:81/bbssndmail";
                result = new PostRequest(Request.Method.POST, url, params, callback, getErrorListener(callback));
                break;
            case BOOK_BOARD:
                url = "http://dian.hust.edu.cn:81/bbsbrdadd?board=" + params.get(ConstantsData.EXTRA_BOARD_NAME) +"&xml=1";
                result = new BookBoardRequest(Request.Method.GET, url, null, callback, getErrorListener(callback));
                break;
            case UN_BOOK_BOARD:
                url = "http://dian.hust.edu.cn:81/bbsbrddel?board=" + params.get(ConstantsData.EXTRA_BOARD_NAME) +"&xml=1";
                result = new BookBoardRequest(Request.Method.GET, url, null, callback, getErrorListener(callback));
                break;
            case MY_FRIENDS:
                url = "http://dian.hust.edu.cn:81/bbsfall?xml=1";
                result = new MyFriendsRequest(Request.Method.GET, url, null, callback, getErrorListener(callback));
                break;
            case ADD_FRIENDS:
                url = "http://dian.hust.edu.cn:81/bbsfadd";
                result = new AddFriendsRequest(Request.Method.POST, url, params, callback, getErrorListener(callback));
                break;
            case DEL_FRIENDS:
                url = "http://dian.hust.edu.cn:81/bbsfdel";
                result = new DelFriendsRequest(Request.Method.POST, url, params, callback, getErrorListener(callback));
                break;

            case MY_NEW_MAILS:
                url = "http://dian.hust.edu.cn:81/bbsgetmsg?xml=1";
                result = new MyNewMailsRequest(Request.Method.GET, url, null, callback, getErrorListener(callback));
                break;
            case INBOX_MAIL:
                url = "http://dian.hust.edu.cn:81/bbsmail?start=&backup=&xml=1";
                result = new MyMailsRequest(Request.Method.GET, url, null, callback, getErrorListener(callback));
                break;
            case OUTBOX_MAIL:
                url = "http://dian.hust.edu.cn:81/bbsmail?start=&backup=1&xml=1";
                result = new MyMailsRequest(Request.Method.GET, url, null, callback, getErrorListener(callback));
                break;
            case MAIL_CONTENT:
                url = "http://dian.hust.edu.cn:81/bbsmailcon";
                result = new MailContentRequest(Request.Method.POST, url, params, callback, getErrorListener(callback));
                break;
            case DEL_MAIL:
                url = "http://dian.hust.edu.cn:81/bbsdelmail?file="+params.get("file")+"&xml=1&backup="+params.get("backup");
                result = new DelMailRequest(Request.Method.GET, url, null, callback, getErrorListener(callback));
                break;
            case REPUBLISH:
                url = "http://dian.hust.edu.cn:81/bbsccc?board="+params.get("srcBoard")
                        +"&file="+params.get("fileName")+"&target="+params.get("toBoard")+"&xml=1";
                result = new RepublishRequest(Request.Method.GET, url, null, callback, getErrorListener(callback));
                break;

            default:
                break;
        }
        Log.d("request", result.getUrl());
        return result;
    }

    /**
     * @param listener
     * @see {@link ByhhAndroidRequest#setOnCookiesDataChangedListener(OnCookiesDataChangedListener)}
     */
    public static void setOnCookiesDataChangedListener(OnCookiesDataChangedListener listener) {
        if (listener == null)
            throw new NullPointerException();

        ByhhAndroidRequest.setOnCookiesDataChangedListener(listener);
    }

    /*---------------------------------------------------------------------------------------
     *------------------------          Image Load                      ---------------------
     *--------------------------------------------------------------------------------------*/
    /**
     * This is object can load image from network.
     * This application only has one imageLoader.
     */
    private static ImageLoader mImageLoader = null;

    private static void initImageLoader() {
        mImageLoader = new ImageLoader(mRequestQueue, LruImageCache.getInstance());
    }

    /**
     * To make the imageView showing the image from network.
     * @param imageView
     * @param url
     * @param defaultImage
     * @param errorImage
     */
    public static void makeNetworkImage(ImageView imageView, String url, int defaultImage, int errorImage) {
        if (url == null || url.equals(""))
            throw new InvalidParameterException();

        if (mImageLoader == null)
            initImageLoader();

        ImageLoader.ImageListener listener = mImageLoader.getImageListener(imageView, defaultImage, errorImage);
        mImageLoader.get(url, listener);
    }

    /**
     * This is object can load image from network.
     * This application only has one imageLoader.
     */
    private static ImageDataLoader mImageDataLoader = null;

    private static void initImageDataLoader() {
        mImageDataLoader = new ImageDataLoader(mRequestQueue, LruImageDataCache.getInstance());
    }

    /**
     * To make the imageView showing the image from network.
     * @param operator
     * @param url
     * @param defaultImage
     * @param errorImage
     */
    public static void makeNetworkImage(ImageDataOperator operator, String url, int defaultImage, int errorImage) {
        if (url == null || url.equals(""))
            throw new InvalidParameterException();

        if (mImageDataLoader == null)
            initImageDataLoader();

        ImageDataLoader.ImageDataListener listener = mImageDataLoader.getListener(operator, defaultImage, errorImage);
        mImageDataLoader.get(url, listener);
    }
}
